package principal;

import java.util.ArrayList;
import java.util.Hashtable;


public class Casamiento {

	private ArrayList<Persona> hombresGS= new ArrayList<Persona>();
	private ArrayList<Persona> hombresBT= new ArrayList<Persona>();
	private Hashtable<String, Persona> mujeresGS= new Hashtable<String, Persona>();
	private ArrayList<Persona> mujeresBT= new ArrayList<Persona>();
	
	
	private void inicializar (ArrayList<String> nombreHombres,ArrayList<String> nombreMujeres, Hashtable<String, ArrayList<String>> preferencias){
		for (int i=0 ; i<nombreHombres.size(); i++){
			this.hombresGS.add(new Persona(nombreHombres.get(i), preferencias.get(nombreHombres.get(i))));
		}
		
		for (int i=0 ; i<nombreMujeres.size(); i++){
			this.mujeresGS.put(nombreMujeres.get(i), new Persona(nombreMujeres.get(i),preferencias.get(nombreMujeres.get(i))));
		}
		
		for (int j=0 ; j<nombreMujeres.size(); j++){
			this.mujeresBT.add(new Persona(nombreMujeres.get(j), preferencias.get(nombreMujeres.get(j))));
		}
		
		for (int i=0 ; i<nombreHombres.size(); i++){
			this.hombresBT.add(new Persona(nombreHombres.get(i), preferencias.get(nombreHombres.get(i))));
		}
		
	}
	
	public Casamiento (ArrayList<String> nombreHombres,ArrayList<String> nombreMujeres,Hashtable<String, ArrayList<String>> preferencias) {
		
		inicializar(nombreHombres,nombreMujeres,preferencias);
		
	}
	
	private void casar (Persona novio1, Persona novio2){
		novio1.comprometer(novio2);
		novio2.comprometer(novio1);
	}
	
	private void divorciar (Persona arrepentido){
		arrepentido.getPrometido().separar();
		arrepentido.separar();
	}
	
	// Algoritmo x Backtracking
	
	private Boolean check (ArrayList<Persona> solucion){

		if (solucion.size()==1 || solucion.isEmpty()) return true;
		else {
			Boolean status=true;
			int i=0;
			
			while (i < solucion.size() && status){
				Persona hombre1=solucion.get(i);
				Persona mujer1=solucion.get(i).getPrometido();
				int j=i+1;
				
				while (j < solucion.size() && status){
					Persona hombre2=solucion.get(j);
					Persona mujer2=solucion.get(j).getPrometido();
					
					if (((hombre1.esMejorPostulante(mujer2) && mujer2.esMejorPostulante(hombre1)) || ((hombre2.esMejorPostulante(mujer1) && mujer1.esMejorPostulante(hombre2))))) status= false;
					else status= true;
					j++;
				}
				i++;
			}
			return status;
		}
	}
	
	public ArrayList<Persona> declararBT (){
		int i=0;
		int j=0;
		ArrayList<Persona> solucion=new ArrayList<Persona>();
		String ex=""; // ultima pareja de un hombre
		
		while (i < this.hombresBT.size()){
			
			
			while (j < this.mujeresBT.size() && this.hombresBT.get(i).estaSoltero()){
				
	
				if (this.mujeresBT.get(j).estaSoltero()&& !(this.mujeresBT.get(j).getNombre()==ex)){
					casar (this.hombresBT.get(i),this.mujeresBT.get(j));
					solucion.add(this.hombresBT.get(i));
					
				} 				
				if (!check(solucion)) {
					divorciar(this.hombresBT.get(i));
					solucion.remove(this.hombresBT.get(i));
				}
				j++;	
			}
			j=0;
			
			if (this.hombresBT.get(i).estaSoltero()) {
				i--;
				ex=this.hombresBT.get(i).getPrometido().getNombre();
				divorciar(this.hombresBT.get(i));
				solucion.remove(this.hombresBT.get(i));
			}
			else {
				i++;
				ex="";
			}
		}
		
		return solucion;
	}

	// Algoritmo x Gale-Shapley
	
	public ArrayList<Persona> declararGS (){
		ArrayList<Persona> solteros= new ArrayList<Persona>(this.hombresGS);
		
		while (!solteros.isEmpty()){
			Persona candidato= this.mujeresGS.get(solteros.get(0).proximaPropuesta());
					
			if (candidato.estaSoltero()) {
				casar(solteros.get(0),candidato);
				solteros.remove(0);
			} else if (candidato.esMejorPostulante(solteros.get(0))) {
				solteros.add(candidato.getPrometido());
				divorciar (candidato);
				casar (solteros.get(0),candidato);	
				solteros.remove(0);
				}
			}
		return this.hombresGS;
		}
}
